#include <stdio.h>
#include <stdlib.h>
#include "../cuda.h"
#define N 10

#define CANTIDAD_THREAD 256
#define CANTIDAD_BLOCKS 65535

__global__ void procesarNodo(int* result, unsigned long long pot) {
	unsigned long long tix = threadIdx.x + blockIdx.x * blockDim.x;
	while (tix < pot) {
		unsigned long long com = tix;
		int valores[N];
		for (int i = 1; i < N; i++) {
			valores[i] = com % N;
			com = com / N;
		};
		valores[0] = com;
		bool cumple = true;
		for (int i = 0; (i < N) && (cumple); i++) {
			for (int j = 0; (j < N) && (cumple); j++) {
				if (i != j) {
					if ((valores[i] == valores[j])
							|| (abs(i - j) == abs(valores[i] - valores[j]))) {
						cumple = false;
					}
				}
			}
		}
		if (cumple) {
			atomicAdd(result, 1);
		}
		tix = tix + (blockDim.x * gridDim.x);
	}
}
;

unsigned long long potencia() {
	unsigned long long aux = 1;
	for (int i = 1; i <= N; i++) {
		aux = N * aux;
	}
	return aux;
}
;

int main(int argc, char *argv[]) {
	unsigned long long pot = potencia();

	int *result_d;
	CudaSafeCall(cudaMalloc((void**) &result_d, sizeof(int)));

	int result = 0;

	CudaSafeCall(
			cudaMemcpy(result_d, &result, sizeof(int), cudaMemcpyHostToDevice));

	procesarNodo<<<CANTIDAD_BLOCKS, CANTIDAD_THREAD>>>(result_d, pot);
	CudaCheckError();

	CudaSafeCall(
			cudaMemcpy(&result, result_d, sizeof(int), cudaMemcpyDeviceToHost));

	printf("Cantidad: %d\n", result);
	return 0;
}
;
